/*import com.alibaba.fastjson.JSON;
import com.qfedu.rongzaiboot.entity.SysLog;
import com.qfedu.rongzaiboot.utils.HttpContextUtils;
import com.qfedu.rongzaiboot.utils.IPUtils;
import com.qfedu.rongzaiboot.utils.ShiroUtils;*/
package com.woniuxy.creditsystem.aspect;
import com.woniuxy.creditsystem.annos.MyLog;
import com.woniuxy.creditsystem.common.bean.SystemLogInfo;
import com.woniuxy.creditsystem.common.bean.UserInfo;
import com.woniuxy.creditsystem.common.util.HttpContextUtils;
import com.woniuxy.creditsystem.common.util.IPUtils;
import com.woniuxy.creditsystem.systemmag.service.ISystemLogService;
import jdk.internal.org.objectweb.asm.tree.TryCatchBlockNode;
import jdk.nashorn.internal.runtime.Context;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Arrays;

/**系统日志 切面处理类
 * @author: hejie
 * @date: 2020/12/15 23:39
 * @description:
 */
@Aspect
@Component
public class SysLogAspect {

    @Resource
    private ISystemLogService systemLogServiceImpl;


    //定义切点 @Pointcut
    //在注解的位置切入代码
    @Pointcut("@annotation(com.woniuxy.creditsystem.annos.MyLog)")
    public void logPoinCut() {
    }

    /**
     * 正常返回通知，拦截用户操作日志，连接点正常执行完成后执行， 如果连接点抛出异常，则不会执行
     * @author hejie
     * @param joinPoint
     */
    //切面 后置返回通知（执行结果都是“成功”）:目标方法正常返回结果之后
    @AfterReturning(value = "logPoinCut()")
    public void saveSysLogIfExcuteOk(JoinPoint joinPoint) {
        System.out.println("\n\n切面 后置返回通知。。。。。saveSysLogIfExcuteOk(目标方法正常返回结果之后)");

        //保存日志
        SystemLogInfo sysLog = new SystemLogInfo();

        //从切面织入点处通过反射机制获取织入点处的方法
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        //获取切入点所在的方法
        Method method = signature.getMethod();

        //获取操作（该操作：使用MyLog注解时，写在注解的括号内：@MyLog(value="xxx")）
        MyLog myLog = method.getAnnotation(MyLog.class);
        if (myLog != null) {
            String value = myLog.value();
            sysLog.setOperation(value);//保存获取的操作
        }
//        sysLog.setOperation(log.value());//保存获取的操作

        //获取请求的类名
        String className = joinPoint.getTarget().getClass().getName();
        //获取请求的方法名
        String methodName = method.getName();
        sysLog.setRequestMethod(className+"."+methodName);

        //请求的参数
        Object[] args = joinPoint.getArgs();
        //这样可以吗？（不用json可以吗）
        String requestParam= Arrays.toString(args);
        if (requestParam.length()>430){
            requestParam= requestParam.substring(0,430)+"...";
        }
        sysLog.setRequestParam(requestParam);
        //将参数所在的数组转换成json
        /*String params = JSON.toJSONString(args);
        sysLog.setParams(params);*/

        //获取用户名
//        sysLog.setUsername(ShiroUtils.getUserEntity().getUsername());
        //如果用户存在，则将用户装配到Shiro 的 Session中
        Subject subject = SecurityUtils.getSubject();
        //这个session是shiro自带的session，不是tomcat的httpSession
        Session session = subject.getSession();
        //存储登录数据
        UserInfo userInfo= (UserInfo) session.getAttribute("user");
        sysLog.setUserInfo(userInfo);

        //获取用户ip地址
        HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
        sysLog.setIp(IPUtils.getIpAddr(request));

        //执行结果：因为是在后置返回通知（目标方法正常执行），所以执行结果是“成功
        sysLog.setExecuteResult(1);
        //错误信息
        sysLog.setErrorInfo("no_errorInfo");
        sysLog.setErrorStack("no_errorStack");
        //调用service保存SysLog实体类到数据库
        systemLogServiceImpl.saveSystemLogBean(sysLog);
    }


    /**
     * 异常返回通知，用于拦截异常日志信息 连接点抛出异常后执行
     * 这个不成功：当用户操作不成功时，事务控制能保证数据库中的内容没有被修改。所以没有必要记录了（实际上：“我去记录”这个saveSystemLogBean(sysLog)，自身也被回滚了、即不能记录异常日志）
     * @author hejie
     * @param joinPoint
     * @param throwable
     */
    //切面 异常通知（执行结果都是“失败”）:目标方法执行有异常（和上面方法相比：仅仅setExecuteResult不同）
    @AfterThrowing(value = "logPoinCut()",throwing = "throwable")
    public void saveSysLogIfExcuteNotOk(JoinPoint joinPoint,Throwable throwable) {
        System.out.println("\n\n切面后置异常通知。。。。。saveSysLogIfExcuteNotOk(目标方法不正常返回结果之后)");

        //保存日志
        SystemLogInfo sysLog = new SystemLogInfo();

        //从切面织入点处通过反射机制获取织入点处的方法
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        //获取切入点所在的方法
        Method method = signature.getMethod();

        //获取操作（该操作：使用MyLog注解时，写在注解的括号内：@MyLog(value="xxx")）
        MyLog myLog = method.getAnnotation(MyLog.class);
        if (myLog != null) {
            String value = myLog.value();
            sysLog.setOperation(value);//保存获取的操作
        }
//        sysLog.setOperation(log.value());//保存获取的操作

        //获取请求的类名
        String className = joinPoint.getTarget().getClass().getName();
        //获取请求的方法名
        String methodName = method.getName();
        sysLog.setRequestMethod(className + "." + methodName);

        //请求参数
        Object[] args = joinPoint.getArgs();
        //这样可以吗？（不用json可以吗）
        String requestParam = Arrays.toString(args);
        if (requestParam.length()>430){
           requestParam= requestParam.substring(0,430)+"...";
        }
        sysLog.setRequestParam(requestParam);
        //将参数所在的数组转换成json
        /*String params = JSON.toJSONString(args);
        sysLog.setParams(params);*/

        //获取用户名
        //如果用户存在，则将用户装配到Shiro 的 Session中
        Subject subject = SecurityUtils.getSubject();
        //这个session是shiro自带的session，不是tomcat的httpSession
        Session session = subject.getSession();
        //存储登录数据
        UserInfo userInfo = (UserInfo) session.getAttribute("user");
        sysLog.setUserInfo(userInfo);

        //获取用户ip地址
        HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
        sysLog.setIp(IPUtils.getIpAddr(request));

        //执行结果：因为是在后置返回通知（目标方法正常执行），所以执行结果是“失败
        sysLog.setExecuteResult(0);
        //错误信息
        sysLog.setErrorInfo(throwable.getMessage());
        sysLog.setErrorStack(throwable.getStackTrace().toString());

        //调用service保存SysLog实体类到数据库
        try {
            systemLogServiceImpl.saveSystemLogBean(sysLog);
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
//            systemLogServiceImpl.saveSystemLogBean(sysLog);
        }
    }

}
